package design;

import java.util.LinkedList;

/**
 * 实现一个拥有如下方法的线程安全有限阻塞队列：
 *
 * BoundedBlockingQueue(int capacity) 构造方法初始化队列，其中capacity代表队列长度上限。
 * void enqueue(int element) 在队首增加一个element. 如果队列满，调用线程被阻塞直到队列非满。
 * int dequeue() 返回队尾元素并从队列中将其删除. 如果队列为空，调用线程被阻塞直到队列非空。
 * int size() 返回当前队列元素个数。
 * 你的实现将会被多线程同时访问进行测试。每一个线程要么是一个只调用enqueue方法的生产者线程，要么是一个只调用dequeue方法的消费者线程。size方法将会在每一个测试用例之后进行调用。
 *
 * 解决方法：
 * 就是生产者消费者问题，可以采用synchronized加等待通知机制，这里用lock和等待通知机制实现一下
 */
public class leetCode1188_BoundedBlockingQueue {

    private LinkedList<Integer> queue = new LinkedList<>();
    private volatile int cap = 0;
    private final Object lock = new Object();
    private int size = 0;


    public leetCode1188_BoundedBlockingQueue(int capacity) {
        this.cap = capacity;
    }

    public void enqueue(int element) throws InterruptedException {
        synchronized (lock){
            while (size == cap){
                lock.wait();
            }
            queue.add(element);
            size++;
            lock.notifyAll();
        }
    }

    public int dequeue() throws InterruptedException {
        synchronized (lock){
            while (size == 0){
                lock.wait();
            }
            Integer integer = queue.pollLast();
            size--;
            lock.notifyAll();
            return integer;
        }
    }

    public int size() {
        return size;
    }
}
